package com.tn.service.dwr;
import javax.jws.WebMethod;
import javax.jws.WebService;

import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.tn.bo.Company;
import com.tn.bo.CreditMemo;
import com.tn.bo.Invoice;
import com.tn.bo.Payment;
import com.tn.bo.UserProfile;
import com.tn.bo.XMLUtil;
import com.tn.dao.CompanyDAO;
import com.tn.dao.InvoiceDAO;
import com.tn.dao.UserDAO;
import com.tn.util.MailService;
import com.tn.wservice.InvoiceApproveRequest;
import com.tn.wservice.PaymentDateCalculator;
import com.tn.xfer.DwrResponse;

@WebService
public class InvoiceDwr {
	private static final Logger logger = Logger.getLogger(InvoiceDwr.class
			.getName());

	public DwrResponse submitInvoice(Invoice invoice) {
		DwrResponse response = new DwrResponse("SUB_INVOICE", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		iDao.insertUpdateInvoice(invoice);
		try {
			sendInvMail(invoice);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return response;
	}

	public DwrResponse submitCreditMemo(CreditMemo cmemo) {
		DwrResponse response = new DwrResponse("SUB_CREDITMEMO", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		iDao.insertUpdateCreditMemoe(cmemo);
		try {
			sendCreditMail(cmemo);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return response;
	}
	
	@WebMethod
	public DwrResponse fetchInvoicesSent(String companyId) {
		DwrResponse response = new DwrResponse("SUB_INVOICE", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		response.setObjRespOrError(iDao.fetchInvoiceSent(companyId));
		return response;
	}

	public DwrResponse fetchInvoicesReceived(String companyId) {
		DwrResponse response = new DwrResponse("SUB_INVOICE", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		response.setObjRespOrError(iDao.fetchInvoicesReceived(companyId));
		return response;
	}

	public DwrResponse postPayment(Payment payment) {
		DwrResponse response = new DwrResponse("SUB_PAYMENT", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		iDao.insertUpdatePayment(payment);
		try {
			sendPaymentMail(payment);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return response;
	}

	public DwrResponse fetchPaymentsSent(String companyId) {
		DwrResponse response = new DwrResponse("SUB_INVOICE", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		response.setObjRespOrError(iDao.fetchPaymentSent(companyId));
		return response;
	}

	public DwrResponse fetchPaymentsReceived(String companyId) {
		DwrResponse response = new DwrResponse("SUB_INVOICE", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		response.setObjRespOrError(iDao.fetchPaymentReceived(companyId));
		return response;
	}

	public DwrResponse fetchCreditMemoSent(String companyId) {
		DwrResponse response = new DwrResponse("SUB_CREDITMEMO", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		response.setObjRespOrError(iDao.fetchCreditMemoSent(companyId));
		return response;
	}

	public DwrResponse fetchCreditMemoReceived(String companyId) {
		DwrResponse response = new DwrResponse("SUB_CREDITMEMO", 0);
		InvoiceDAO iDao = new InvoiceDAO();
		response.setObjRespOrError(iDao.fetchCreditMemoReceived(companyId));
		return response;
	}

	public DwrResponse updateInvoice(String invId,
			ArrayList<String> newAttachmentList,
			ArrayList<String> newCommentsList, String updatedBy) {
		DwrResponse response = new DwrResponse("UPDATE_INVOICE", 0);
		try {
			InvoiceDAO iDao = new InvoiceDAO();
			Invoice inv = iDao.getLatestInvoice(invId);

			if (inv.getInvoiceAttachmentsId() != null) {
				inv.getInvoiceAttachmentsId().addAll(newAttachmentList);
			} else {
				inv.setInvoiceAttachmentsId(newAttachmentList);
			}

			if (inv.getInvoiceComments() != null) {
				inv.getInvoiceComments().addAll(newCommentsList);
			} else {
				inv.setInvoiceComments(newCommentsList);
			}

			inv.setInvoiceVersion(inv.getInvoiceVersion() + 1);
			inv.setUniqueInvoiceNumber(inv.getUniqueInvoiceNumber() + "v"
					+ inv.getInvoiceVersion());
			inv.setLastModifiedDate(new Date());
			inv.setLastModifiedBy(updatedBy);

			iDao.updateInvoice(inv);

			inv = iDao.getLatestInvoice(invId);
			try {
				inv.setInvoiceHistory(iDao.getInvoiceHistory(invId));
				inv.setInvoiceXml(XMLUtil.getInvoiceXml(inv));
			} catch (Exception ex) {
			}
			response.setObjRespOrError(inv);

		} catch (Exception ex) {
			logger.log(Level.SEVERE, "Error while updating invoice:", ex);
			ex.printStackTrace();
			response.setObjRespOrError(ex);
			response.setRespCode(-1);
		}

		return response;
	}

	public DwrResponse updatePayment(String pmtId,
			ArrayList<String> newAttachmentList,
			ArrayList<String> newCommentsList, String updatedBy) {
		DwrResponse response = new DwrResponse("UPDATE_INVOICE", 0);
		try {
			InvoiceDAO iDao = new InvoiceDAO();
			Payment pmt = iDao.getLatestPayment(pmtId);

			if (pmt.getPaymentAttachmentIds() != null) {
				pmt.getPaymentAttachmentIds().addAll(newAttachmentList);
			} else {
				pmt.setPaymentAttachmentIds(newAttachmentList);
			}

			if (pmt.getPaymentComments() != null) {
				pmt.getPaymentComments().addAll(newCommentsList);
			} else {
				pmt.setPaymentComments(newCommentsList);
			}

			pmt.setPaymentVersion(pmt.getPaymentVersion() + 1);
			pmt.setUniquePaymentNumber(pmt.getUniquePaymentNumber() + "v"
					+ pmt.getPaymentVersion());
			pmt.setLastModifiedDate(new Date());
			pmt.setLastModifiedBy(updatedBy);

			iDao.updatePayment(pmt);

			pmt = iDao.getLatestPayment(pmtId);

			pmt.setPaymentHistory(iDao.getPaymentHistory(pmtId));
			pmt.setPaymentXml(XMLUtil.getPaymentXml(pmt));
			response.setObjRespOrError(pmt);

		} catch (Exception ex) {
			ex.printStackTrace();
			response.setObjRespOrError(ex);
			response.setRespCode(-1);
		}

		return response;
	}

	public DwrResponse updateCreditMemo(String cmemoId,
			ArrayList<String> newAttachmentList,
			ArrayList<String> newCommentsList, String updatedBy) {
		DwrResponse response = new DwrResponse("UPDATE_CREDITMEMO", 0);
		try {
			InvoiceDAO iDao = new InvoiceDAO();
			CreditMemo pmt = iDao.getLatestCreditMemo(cmemoId);

			if (pmt.getCreditmemoAttachmentIds() != null) {
				pmt.getCreditmemoAttachmentIds().addAll(newAttachmentList);
			} else {
				pmt.setCreditmemoAttachmentIds(newAttachmentList);
			}

			if (pmt.getCreditMemoComments() != null) {
				pmt.getCreditMemoComments().addAll(newCommentsList);
			} else {
				pmt.setCreditMemoComments(newCommentsList);
			}

			pmt.setCreditMemoVersion(pmt.getCreditMemoVersion() + 1);
			pmt.setUniqueCreditMemoNumber(pmt.getUniqueCreditMemoNumber() + "v"
					+ pmt.getCreditMemoVersion());
			pmt.setLastModifiedDate(new Date());
			pmt.setLastModifiedBy(updatedBy);

			iDao.updateCreditMemo(pmt);

			pmt = iDao.getLatestCreditMemo(cmemoId);

			pmt.setCreditMemoHistory(iDao.getCreditMemoHistory(cmemoId));
			pmt.setCreditMemoXml(XMLUtil.getCreditMemoXml(pmt));
			response.setObjRespOrError(pmt);

		} catch (Exception ex) {
			ex.printStackTrace();
			response.setObjRespOrError(ex);
			response.setRespCode(-1);
		}

		return response;
	}

	public static Logger getLogger() {
		return logger;
	}

	private void sendInvMail(Invoice invoice) throws Exception {
		String fromCompanyId = invoice.getMainSupplierCompnay();
		String toCompanyId = invoice.getInvoicedToCompany();

		UserDAO userDAO = new UserDAO();
		CompanyDAO companyDAO = new CompanyDAO();
		if (fromCompanyId != null && !"".equals(fromCompanyId)) {
			Company company = companyDAO.findCompanyByCompanyId(fromCompanyId);
			if (company != null && company.getEmailPreferences() != null
					&& company.getEmailPreferences().isInvsent()) {
				ArrayList<UserProfile> userProfileList = userDAO.getByProperty(
						"companyId", company.getCompanyId());
				for (int i = 0; i < userProfileList.size(); i++) {
					UserProfile userProfile = userProfileList.get(i);
					if (userProfile != null) {
						String email = userProfile.getEmailAddress();
						if (email != null) {
							MailService mailService = new MailService();
							mailService.sendInvSentMail(email, invoice); // receiver
						}
					}
				}
			}
		}

		if (toCompanyId != null && !"".equals(toCompanyId)) {
			Company company = companyDAO.findCompanyByCompanyId(toCompanyId);
			if (company != null && company.getEmailPreferences() != null
					&& company.getEmailPreferences().isInvreceived()) {
				ArrayList<UserProfile> userProfileList = userDAO.getByProperty(
						"companyId", company.getCompanyId());
				for (int i = 0; i < userProfileList.size(); i++) {
					UserProfile userProfile = userProfileList.get(i);
					if (userProfile != null) {
						String email = userProfile.getEmailAddress();
						if (email != null) {
							MailService mailService = new MailService();
							mailService.sendInvRecvMail(email, invoice); // sender
						}
					}
				}
			}
		}

		// TODO: add condition for super user mail only and not all

	}

	private void sendCreditMail(CreditMemo cmemo) {
		String fromCompanyId = cmemo.getMainSupplierCompany();
		String toCompanyId = cmemo.getCreditMemoToCompany();

		UserDAO userDAO = new UserDAO();
		CompanyDAO companyDAO = new CompanyDAO();
		if (fromCompanyId != null && !"".equals(fromCompanyId)) {
			Company company = companyDAO.findCompanyByCompanyId(fromCompanyId);
			if (company != null && company.getEmailPreferences() != null
					&& company.getEmailPreferences().isCrdsent()) {
				ArrayList<UserProfile> userProfileList = userDAO.getByProperty(
						"companyId", company.getCompanyId());
				for (int i = 0; i < userProfileList.size(); i++) {
					UserProfile userProfile = userProfileList.get(i);
					if (userProfile != null) {
						String email = userProfile.getEmailAddress();
						if (email != null) {
							MailService mailService = new MailService();
							mailService.sendCreditSentMail(email, cmemo); // receiver
						}
					}
				}
			}
		}

		if (toCompanyId != null && !"".equals(toCompanyId)) {
			Company company = companyDAO.findCompanyByCompanyId(toCompanyId);
			if (company != null && company.getEmailPreferences() != null
					&& company.getEmailPreferences().isCrdreceived()) {
				ArrayList<UserProfile> userProfileList = userDAO.getByProperty(
						"companyId", company.getCompanyId());
				for (int i = 0; i < userProfileList.size(); i++) {
					UserProfile userProfile = userProfileList.get(i);
					if (userProfile != null) {
						String email = userProfile.getEmailAddress();
						if (email != null) {
							MailService mailService = new MailService();
							mailService.sendCreditRecvMail(email, cmemo); // sender
						}
					}
				}
			}
		}

		// TODO: add condition for super user mail only and not alls

	}

	private void sendPaymentMail(Payment payment) {
		String fromCompanyId = payment.getOriginatingCompany();
		String toCompanyId = payment.getPaymentRecipientMainCompany();

		UserDAO userDAO = new UserDAO();
		CompanyDAO companyDAO = new CompanyDAO();
		if (fromCompanyId != null && !"".equals(fromCompanyId)) {
			Company company = companyDAO.findCompanyByCompanyId(fromCompanyId);
			if (company != null && company.getEmailPreferences() != null
					&& company.getEmailPreferences().isPymtsent()) {
				ArrayList<UserProfile> userProfileList = userDAO.getByProperty(
						"companyId", company.getCompanyId());
				for (int i = 0; i < userProfileList.size(); i++) {
					UserProfile userProfile = userProfileList.get(i);
					if (userProfile != null) {
						String email = userProfile.getEmailAddress();
						if (email != null) {
							MailService mailService = new MailService();
							mailService.sendPaymentSentMail(email, payment); // receiver
						}
					}
				}
			}
		}

		if (toCompanyId != null && !"".equals(toCompanyId)) {
			Company company = companyDAO.findCompanyByCompanyId(toCompanyId);
			if (company != null && company.getEmailPreferences() != null
					&& company.getEmailPreferences().isPymtreceived()) {
				ArrayList<UserProfile> userProfileList = userDAO.getByProperty(
						"companyId", company.getCompanyId());
				for (int i = 0; i < userProfileList.size(); i++) {
					UserProfile userProfile = userProfileList.get(i);
					if (userProfile != null) {
						String email = userProfile.getEmailAddress();
						if (email != null) {
							MailService mailService = new MailService();
							mailService.sendPaymentRecvMail(email, payment); // sender
						}
					}
				}
			}
		}

		// TODO: add condition for super user mail only and not alls

	}

	public DwrResponse approveInvoice(InvoiceApproveRequest request) {
		DwrResponse response = new DwrResponse("APPROVE_INVOICE", 0);
		try {
			InvoiceDAO iDao = new InvoiceDAO();
			String invoiceNumber = request.getInvoiceNumber();
			Invoice inv = iDao.getLatestInvoice(invoiceNumber);

			inv.setInvoiceVersion(inv.getInvoiceVersion() + 1);
			inv.setUniqueInvoiceNumber(inv.getUniqueInvoiceNumber() + "v"
					+ inv.getInvoiceVersion());
			inv.setLastModifiedDate(new Date());
			inv.setLastModifiedBy(request.getUserId());
			inv.setApproveDate(new Date());
			
			Date paymentDate = PaymentDateCalculator.getPaymentDate(inv);
			inv.setExpectedPaymentDate(paymentDate);

			iDao.updateInvoice(inv);

			inv = iDao.getLatestInvoice(invoiceNumber);
			try {
				inv.setInvoiceHistory(iDao.getInvoiceHistory(invoiceNumber));
				inv.setInvoiceXml(XMLUtil.getInvoiceXml(inv));
			} catch (Exception ex) {
			}
			response.setObjRespOrError(inv);
		} catch (Exception ex) {
			logger.log(Level.SEVERE, "Error while approving invoice:", ex);
			ex.printStackTrace();
			response.setObjRespOrError(ex);
			response.setRespCode(-1);
		}
		return response;
	}
}
